package edu.washington.cs.workflow.analysis;

import java.util.HashSet;
import java.util.Set;

import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.ipa.cha.ClassHierarchy;
import com.ibm.wala.ssa.SSAInvokeInstruction;

import edu.washington.cs.workflow.analysis.AnalysisBuilder.CG;
import edu.washington.cs.workflow.analysis.AnalysisBuilder.UIFramework;

/**
 * Check whether a given method is of interest as an event-handling method
 * */
public class EventHandlerManager {

	private Set<String> addListenerMethods = null;
	private Set<String> initListenerMethods() {
		Set<String> allMethods = new HashSet<String>();
		allMethods.add("addAction");
		allMethods.add("setAction");
		allMethods.add("addMouseMotionListener");
		allMethods.add("addInputMethodListener");
		allMethods.add("addContainerListener");
		allMethods.add("addMenuListener");
		allMethods.add("addMouseWheelListener");
		allMethods.add("addHyperlinkListener");
		allMethods.add("addPropertyChangeListener");
		allMethods.add("addAncestorListener");
		allMethods.add("addActionListener");
		allMethods.add("addItemListener");
		allMethods.add("addMouseListener");
		allMethods.add("addHierarchyBoundsListener");
		allMethods.add("addFocusListener");
		allMethods.add("addInternalFrameListener");
		allMethods.add("addTreeWillExpandListener");
		allMethods.add("addListSelectionListener");
		allMethods.add("addHierarchyListener");
		allMethods.add("addChangeListener");
		allMethods.add("addTreeExpansionListener");
		allMethods.add("addPopupMenuListener");
		allMethods.add("addKeyListener");
		allMethods.add("addComponentListener");
		allMethods.add("addVetoableChangeListener");
		allMethods.add("addMenuKeyListener");
		allMethods.add("addCaretListener");
		allMethods.add("addTreeSelectionListener");
		allMethods.add("addMenuDragMouseListener");
		allMethods.add("addAdjustmentListener");
		return allMethods;
	}
	
	public boolean isEventHandlerAdditionCall(SSAInvokeInstruction invoke) {
		if(addListenerMethods == null) {
			addListenerMethods = this.initListenerMethods();
		}
		String methodName = invoke.getCallSite().getDeclaredTarget().getName().toString();
		return addListenerMethods.contains(methodName);
	}
	
	/**
	 * Print all methods for adding listeners
	 * */
	public static void printAllListenerAddingMethods() {
		String[] pkgs = new String[]{"crosswordsage"};
		String dir = "D:\\research\\configurations\\workspace\\workflow-error-repair\\experiments\\crossword-0.3.5.jar";
		String main = "Lcrosswordsage/MainScreen";
		
		AnalysisBuilder builder = new AnalysisBuilder(dir, main, pkgs);
		builder.setCGType(CG.RTA);
		builder.setUIFramework(UIFramework.SWING);
		builder.buildAnalysis();
		
		Set<String> ms = new HashSet<String>();
		ClassHierarchy cha = builder.getClassHierarchy();
		int n = 0;
		for(IClass c : cha) {
			if(SwingHelper.isSwingComponentClass(cha, c)) {
				n++;
				for(IMethod m : c.getAllMethods()) {
					String mstr = m.getName().toString();
					if(mstr.startsWith("add") && mstr.endsWith("Listener")) {
//						System.out.println(mstr);
						ms.add(mstr);
					}
				}
			}
		}
		System.out.println("Num of classes: " + n);
		System.out.println();
		System.out.println("Methods: " + ms.size());
		for(String m : ms) {
			System.out.println(m);
		}
	}
	
	public static void main(String[] args) {
		new EventHandlerManager().printAllListenerAddingMethods();
	}
}